"""
IP管理工具函数
提供IP地址验证、格式化等工具方法
"""

import logging
import ipaddress
import re
from typing import Dict, Any, List, Optional, Tuple
from datetime import datetime

from src.app.database.models import IpManagement

logger = logging.getLogger(__name__)

class IpUtils:
    """IP管理工具类"""
    
    # IP地址状态常量
    STATUS_IN_USE = "使用中"
    STATUS_AVAILABLE = "可用"
    STATUS_RESERVED = "预留"
    STATUS_DISABLED = "禁用"
    
    # IP用途常量
    PURPOSE_MANAGEMENT = "管理"
    PURPOSE_BUSINESS = "业务"
    PURPOSE_STORAGE = "存储"
    PURPOSE_BACKUP = "备份"
    PURPOSE_MONITOR = "监控"
    PURPOSE_TEST = "测试"
    
    # 分配期限常量
    DURATION_PERMANENT = "永久"
    DURATION_TEMPORARY = "临时"
    DURATION_PROJECT = "项目期间"
    DURATION_CONTRACT = "合同期间"
    
    def __init__(self):
        # 支持的IP状态
        self.valid_statuses = [
            self.STATUS_IN_USE,
            self.STATUS_AVAILABLE,
            self.STATUS_RESERVED,
            self.STATUS_DISABLED
        ]
        
        # 支持的IP用途
        self.valid_purposes = [
            self.PURPOSE_MANAGEMENT,
            self.PURPOSE_BUSINESS,
            self.PURPOSE_STORAGE,
            self.PURPOSE_BACKUP,
            self.PURPOSE_MONITOR,
            self.PURPOSE_TEST
        ]
        
        # 支持的分配期限
        self.valid_durations = [
            self.DURATION_PERMANENT,
            self.DURATION_TEMPORARY,
            self.DURATION_PROJECT,
            self.DURATION_CONTRACT
        ]
        
        logger.info("IP管理工具初始化完成")
    
    def validate_ip_data(self, ip_data: Dict[str, Any], is_update: bool = False) -> Tuple[bool, str]:
        """
        验证IP数据
        
        Args:
            ip_data: IP数据
            is_update: 是否为更新操作
            
        Returns:
            (是否有效, 错误信息)
        """
        try:
            # 必填字段验证
            required_fields = ['ip', 'subnet_mask', 'vlan', 'purpose', 'status', 'allocation_duration']
            for field in required_fields:
                if is_update and field not in ip_data:
                    continue
                    
                if field in ip_data and ip_data[field] is None:
                    return False, f"字段 {field} 不能为空"
                
                if not is_update and field not in ip_data:
                    return False, f"缺少必填字段: {field}"
            
            # IP地址格式验证
            if 'ip' in ip_data and ip_data['ip']:
                if not self.is_valid_ip(ip_data['ip']):
                    return False, "IP地址格式无效"
            
            # 子网掩码验证
            if 'subnet_mask' in ip_data and ip_data['subnet_mask']:
                if not self.is_valid_subnet_mask(ip_data['subnet_mask']):
                    return False, "子网掩码格式无效"
            
            # VLAN验证
            if 'vlan' in ip_data and ip_data['vlan']:
                if not self.is_valid_vlan(ip_data['vlan']):
                    return False, "VLAN格式无效"
            
            # 状态验证
            if 'status' in ip_data and ip_data['status']:
                if ip_data['status'] not in self.valid_statuses:
                    return False, f"无效的状态: {ip_data['status']}"
            
            # 用途验证
            if 'purpose' in ip_data and ip_data['purpose']:
                if ip_data['purpose'] not in self.valid_purposes:
                    return False, f"无效的用途: {ip_data['purpose']}"
            
            # 分配期限验证
            if 'allocation_duration' in ip_data and ip_data['allocation_duration']:
                if ip_data['allocation_duration'] not in self.valid_durations:
                    return False, f"无效的分配期限: {ip_data['allocation_duration']}"
            
            # 绑定实体验证 - 确保只能绑定到一个实体
            entity_fields = ['asset_id', 'os_id', 'system_id', 'mw_id', 'oob_id']
            bound_entities = [field for field in entity_fields 
                            if field in ip_data and ip_data[field]]
            
            if len(bound_entities) > 1:
                return False, "IP地址只能绑定到一个实体"
            
            return True, ""
            
        except Exception as e:
            logger.error(f"IP数据验证失败: {str(e)}")
            return False, f"验证失败: {str(e)}"
    
    def is_valid_ip(self, ip: str) -> bool:
        """
        验证IP地址格式
        
        Args:
            ip: IP地址
            
        Returns:
            是否有效
        """
        try:
            ipaddress.ip_address(ip)
            return True
        except ValueError:
            return False
    
    def is_valid_subnet_mask(self, mask: str) -> bool:
        """
        验证子网掩码格式
        
        Args:
            mask: 子网掩码
            
        Returns:
            是否有效
        """
        try:
            # 检查是否为有效的子网掩码
            ipaddress.ip_address(mask)
            
            # 检查是否为有效的子网掩码（连续的1后面跟连续的0）
            mask_int = int(ipaddress.ip_address(mask))
            # 检查掩码是否为有效的格式
            binary_str = bin(mask_int)[2:].zfill(32)
            
            # 检查是否为连续的1后面跟连续的0
            if '01' in binary_str:
                return False
            
            return True
        except ValueError:
            return False
    
    def is_valid_vlan(self, vlan: str) -> bool:
        """
        验证VLAN格式
        
        Args:
            vlan: VLAN标识
            
        Returns:
            是否有效
        """
        # VLAN可以是数字或者VLAN+数字的格式
        vlan_pattern = r'^(VLAN\d+|\d+)$'
        return bool(re.match(vlan_pattern, vlan.upper()))
    
    def normalize_vlan(self, vlan: str) -> str:
        """
        标准化VLAN格式
        
        Args:
            vlan: VLAN标识
            
        Returns:
            标准化后的VLAN
        """
        vlan = vlan.upper().strip()
        
        # 如果是纯数字，添加VLAN前缀
        if vlan.isdigit():
            return f"VLAN{vlan}"
        
        return vlan
    
    def ip_to_dict(self, ip: IpManagement) -> Dict[str, Any]:
        """
        将IP对象转换为字典
        
        Args:
            ip: IP对象
            
        Returns:
            IP数据字典
        """
        return {
            'ip': ip.ip,
            'subnet_mask': ip.subnet_mask,
            'vlan': ip.vlan,
            'purpose': ip.purpose,
            'status': ip.status,
            'allocation_duration': ip.allocation_duration,
            'asset_id': ip.asset_id,
            'os_id': ip.os_id,
            'system_id': ip.system_id,
            'mw_id': ip.mw_id,
            'oob_id': ip.oob_id,
            'os_name': ip.os_name,
            'hostname': ip.hostname,
            'description': ip.description,
            'create_time': ip.create_time.isoformat() if ip.create_time else None,
            'update_time': ip.update_time.isoformat() if ip.update_time else None
        }
    
    def get_network_info(self, ip: str, subnet_mask: str) -> Dict[str, Any]:
        """
        获取网络信息
        
        Args:
            ip: IP地址
            subnet_mask: 子网掩码
            
        Returns:
            网络信息
        """
        try:
            ip_obj = ipaddress.ip_address(ip)
            mask_obj = ipaddress.ip_address(subnet_mask)
            network = ipaddress.ip_network(f"{ip}/{subnet_mask}", strict=False)
            
            return {
                'ip': str(ip_obj),
                'subnet_mask': str(mask_obj),
                'network_address': str(network.network_address),
                'broadcast_address': str(network.broadcast_address),
                'netmask': str(network.netmask),
                'prefix_length': network.prefixlen,
                'num_addresses': network.num_addresses,
                'is_private': ip_obj.is_private,
                'is_loopback': ip_obj.is_loopback,
                'is_multicast': ip_obj.is_multicast,
                'is_reserved': ip_obj.is_reserved
            }
        except Exception as e:
            logger.error(f"获取网络信息失败: {str(e)}")
            return {}
    
    def get_ip_range(self, network: str) -> List[str]:
        """
        获取IP地址范围内的所有可用IP
        
        Args:
            network: 网络地址（如192.168.1.0/24）
            
        Returns:
            IP地址列表
        """
        try:
            net = ipaddress.ip_network(network, strict=False)
            return [str(ip) for ip in net.hosts()]
        except Exception as e:
            logger.error(f"获取IP范围失败: {str(e)}")
            return []
    
    def calculate_subnet_capacity(self, subnet_mask: str) -> Dict[str, Any]:
        """
        计算子网容量
        
        Args:
            subnet_mask: 子网掩码
            
        Returns:
            子网容量信息
        """
        try:
            # 计算子网掩码的位数
            mask_obj = ipaddress.ip_address(subnet_mask)
            mask_int = int(mask_obj)
            prefix_length = bin(mask_int).count('1')
            
            # 计算可用IP数量
            if prefix_length >= 31:
                usable_ips = 0
            else:
                usable_ips = 2 ** (32 - prefix_length) - 2
            
            return {
                'subnet_mask': subnet_mask,
                'prefix_length': prefix_length,
                'total_ips': 2 ** (32 - prefix_length),
                'usable_ips': usable_ips,
                'network_address_count': 1,
                'broadcast_address_count': 1
            }
        except Exception as e:
            logger.error(f"计算子网容量失败: {str(e)}")
            return {}
    
    def format_ip_status(self, status: str) -> str:
        """
        格式化IP状态显示
        
        Args:
            status: 状态
            
        Returns:
            格式化后的状态
        """
        status_map = {
            self.STATUS_IN_USE: "🟢 使用中",
            self.STATUS_AVAILABLE: "🔵 可用",
            self.STATUS_RESERVED: "🟡 预留",
            self.STATUS_DISABLED: "🔴 禁用"
        }
        return status_map.get(status, status)
    
    def format_purpose(self, purpose: str) -> str:
        """
        格式化IP用途显示
        
        Args:
            purpose: 用途
            
        Returns:
            格式化后的用途
        """
        purpose_map = {
            self.PURPOSE_MANAGEMENT: "🖥️ 管理",
            self.PURPOSE_BUSINESS: "💼 业务",
            self.PURPOSE_STORAGE: "💾 存储",
            self.PURPOSE_BACKUP: "📦 备份",
            self.PURPOSE_MONITOR: "📊 监控",
            self.PURPOSE_TEST: "🧪 测试"
        }
        return purpose_map.get(purpose, purpose)
    
    def get_binding_entity_type(self, ip_data: Dict[str, Any]) -> str:
        """
        获取IP绑定的实体类型
        
        Args:
            ip_data: IP数据
            
        Returns:
            实体类型
        """
        if ip_data.get('asset_id'):
            return "设备资产"
        elif ip_data.get('os_id'):
            return "操作系统"
        elif ip_data.get('system_id'):
            return "业务系统"
        elif ip_data.get('mw_id'):
            return "中间件"
        elif ip_data.get('oob_id'):
            return "带外管理"
        else:
            return "未绑定"
    
    def get_entity_binding_options(self) -> List[Dict[str, str]]:
        """
        获取实体绑定选项
        
        Returns:
            绑定选项列表
        """
        return [
            {'value': 'asset', 'label': '设备资产'},
            {'value': 'os', 'label': '操作系统'},
            {'value': 'system', 'label': '业务系统'},
            {'value': 'middleware', 'label': '中间件'},
            {'value': 'oob', 'label': '带外管理'}
        ]
    
    def get_status_options(self) -> List[Dict[str, str]]:
        """
        获取状态选项
        
        Returns:
            状态选项列表
        """
        return [
            {'value': self.STATUS_AVAILABLE, 'label': self.format_ip_status(self.STATUS_AVAILABLE)},
            {'value': self.STATUS_IN_USE, 'label': self.format_ip_status(self.STATUS_IN_USE)},
            {'value': self.STATUS_RESERVED, 'label': self.format_ip_status(self.STATUS_RESERVED)},
            {'value': self.STATUS_DISABLED, 'label': self.format_ip_status(self.STATUS_DISABLED)}
        ]
    
    def get_purpose_options(self) -> List[Dict[str, str]]:
        """
        获取用途选项
        
        Returns:
            用途选项列表
        """
        return [
            {'value': self.PURPOSE_MANAGEMENT, 'label': self.format_purpose(self.PURPOSE_MANAGEMENT)},
            {'value': self.PURPOSE_BUSINESS, 'label': self.format_purpose(self.PURPOSE_BUSINESS)},
            {'value': self.PURPOSE_STORAGE, 'label': self.format_purpose(self.PURPOSE_STORAGE)},
            {'value': self.PURPOSE_BACKUP, 'label': self.format_purpose(self.PURPOSE_BACKUP)},
            {'value': self.PURPOSE_MONITOR, 'label': self.format_purpose(self.PURPOSE_MONITOR)},
            {'value': self.PURPOSE_TEST, 'label': self.format_purpose(self.PURPOSE_TEST)}
        ]
    
    def get_duration_options(self) -> List[Dict[str, str]]:
        """
        获取分配期限选项
        
        Returns:
            分配期限选项列表
        """
        return [
            {'value': self.DURATION_PERMANENT, 'label': self.DURATION_PERMANENT},
            {'value': self.DURATION_TEMPORARY, 'label': self.DURATION_TEMPORARY},
            {'value': self.DURATION_PROJECT, 'label': self.DURATION_PROJECT},
            {'value': self.DURATION_CONTRACT, 'label': self.DURATION_CONTRACT}
        ]
    
    def validate_ip_subnet_match(self, ip: str, subnet_mask: str, network: str) -> bool:
        """
        验证IP是否属于指定网络
        
        Args:
            ip: IP地址
            subnet_mask: 子网掩码
            network: 网络地址
            
        Returns:
            是否匹配
        """
        try:
            ip_obj = ipaddress.ip_address(ip)
            network_obj = ipaddress.ip_network(network, strict=False)
            return ip_obj in network_obj
        except ValueError:
            return False
    
    def get_next_available_ip(self, network: str, used_ips: List[str]) -> Optional[str]:
        """
        获取下一个可用IP地址
        
        Args:
            network: 网络地址
            used_ips: 已使用的IP列表
            
        Returns:
            下一个可用IP或None
        """
        try:
            network_obj = ipaddress.ip_network(network, strict=False)
            used_ip_set = set(used_ips)
            
            for ip in network_obj.hosts():
                if str(ip) not in used_ip_set:
                    return str(ip)
            
            return None
        except ValueError:
            return None
    
    def export_to_dict_list(self, ip_data_list: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        导出IP数据为字典列表
        
        Args:
            ip_data_list: IP数据列表
            
        Returns:
            导出的数据列表
        """
        exported_data = []
        
        for ip_data in ip_data_list:
            exported_item = {
                'IP地址': ip_data['ip'],
                '子网掩码': ip_data['subnet_mask'],
                'VLAN': ip_data['vlan'],
                '用途': ip_data['purpose'],
                '状态': ip_data['status'],
                '分配期限': ip_data['allocation_duration'],
                '操作系统名称': ip_data.get('os_name', ''),
                '主机名': ip_data.get('hostname', ''),
                '描述': ip_data.get('description', ''),
                '绑定实体': self.get_binding_entity_type(ip_data),
                '创建时间': ip_data.get('create_time', ''),
                '更新时间': ip_data.get('update_time', '')
            }
            exported_data.append(exported_item)
        
        return exported_data
